package service

import (
	"errors"
	"fmt"
	"log"
	"sync"
	"time"

	"github.com/slrun/callcenter/internal/model"
	"github.com/slrun/callcenter/internal/pkg/freeswitch"
	"github.com/slrun/callcenter/internal/pkg/kamailio"
)

// AgentService 座席管理服务
type AgentService struct {
	agents           map[string]*model.Agent
	agentSettings    map[string]*model.AgentSettings
	agentActivities  map[string]*model.AgentActivity
	currentActivities map[string]*model.AgentActivity // 当前活动
	fsClient         *freeswitch.Client
	kamailioClient   *kamailio.Client
	acdEngine        *ACDEngine
	mutex            sync.RWMutex
}

// NewAgentService 创建座席管理服务
func NewAgentService(fsClient *freeswitch.Client, kamailioClient *kamailio.Client, acdEngine *ACDEngine) *AgentService {
	return &AgentService{
		agents:           make(map[string]*model.Agent),
		agentSettings:    make(map[string]*model.AgentSettings),
		agentActivities:  make(map[string]*model.AgentActivity),
		currentActivities: make(map[string]*model.AgentActivity),
		fsClient:         fsClient,
		kamailioClient:   kamailioClient,
		acdEngine:        acdEngine,
	}
}

// 座席登录相关

// Login 座席登录
func (s *AgentService) Login(agentID, password string) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 验证座席存在
	agent, exists := s.agents[agentID]
	if !exists {
		return errors.New("agent not found")
	}

	// 验证密码
	if agent.Password != password {
		return errors.New("invalid password")
	}

	// 检查是否已经登录
	if agent.Status != model.AgentStatusOffline {
		return errors.New("agent already logged in")
	}

	// 更新座席状态为已登录
	agent.Status = model.AgentStatusLoggedIn
	now := time.Now()
	agent.LoginTime = &now
	agent.LastActivity = &now

	// 创建登录活动记录
	activity := &model.AgentActivity{
		ID:           fmt.Sprintf("activity_%d_%s", now.UnixNano(), agentID),
		AgentID:      agentID,
		ActivityType: "login",
		Status:       agent.Status,
		StartTime:    now,
		Notes:        "Agent logged in",
	}
	s.agentActivities[activity.ID] = activity
	s.currentActivities[agentID] = activity

	// 在Kamailio中注册用户
	if s.kamailioClient != nil {
		// 修复AddUser调用，使用正确的参数格式
		err := s.kamailioClient.AddUser(agent.Extension, agent.Password)
		if err != nil {
			log.Printf("Failed to register agent %s in Kamailio: %v", agentID, err)
		}
	}

	log.Printf("Agent %s (%s) logged in successfully", agent.FullName, agentID)
	return nil
}

// Logout 座席登出
func (s *AgentService) Logout(agentID string) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 验证座席存在
	agent, exists := s.agents[agentID]
	if !exists {
		return errors.New("agent not found")
	}

	// 检查是否已经离线
	if agent.Status == model.AgentStatusOffline {
		return errors.New("agent already offline")
	}

	// 如果有进行中的通话，先结束通话
	if agent.CurrentCallID != "" {
		if s.fsClient != nil {
			err := s.fsClient.HangupCall(agent.CurrentCallID)
			if err != nil {
				log.Printf("Failed to hangup call %s for agent %s: %v", agent.CurrentCallID, agentID, err)
			}
		}
		agent.CurrentCallID = ""
	}

	// 结束当前活动
	now := time.Now()
	if activity, exists := s.currentActivities[agentID]; exists {
		activity.EndTime = &now
		activity.Duration = int(now.Sub(activity.StartTime).Seconds())
		delete(s.currentActivities, agentID)
	}

	// 创建登出活动记录
	logoutActivity := &model.AgentActivity{
		ID:           fmt.Sprintf("activity_%d_%s", now.UnixNano(), agentID),
		AgentID:      agentID,
		ActivityType: "logout",
		Status:       agent.Status,
		StartTime:    now,
		Notes:        "Agent logged out",
	}
	s.agentActivities[logoutActivity.ID] = logoutActivity

	// 从ACD队列中移除座席
	if s.acdEngine != nil {
		// 从所有队列中移除座席
		queues := s.acdEngine.ListQueues()
		for _, queue := range queues {
			_ = s.acdEngine.RemoveAgentFromQueue(agentID, queue.ID)
		}
	}

	// 在Kamailio中注销用户
	if s.kamailioClient != nil {
		// 修复RemoveUser调用，只传递用户名
		err := s.kamailioClient.RemoveUser(agent.Extension)
		if err != nil {
			log.Printf("Failed to unregister agent %s from Kamailio: %v", agentID, err)
		}
	}

	// 更新座席状态为离线
	agent.Status = model.AgentStatusOffline
	agent.LogoutTime = &now
	agent.LastActivity = &now

	log.Printf("Agent %s (%s) logged out successfully", agent.FullName, agentID)
	return nil
}

// 座席状态管理

// ChangeStatus 变更座席状态
func (s *AgentService) ChangeStatus(agentID string, newStatus model.AgentStatus) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 验证座席存在
	agent, exists := s.agents[agentID]
	if !exists {
		return errors.New("agent not found")
	}

	// 检查状态变更是否有效
	if !s.isValidStatusChange(agent.Status, newStatus) {
		return fmt.Errorf("invalid status change from %s to %s", agent.Status, newStatus)
	}

	// 结束当前活动
	now := time.Now()
	if activity, exists := s.currentActivities[agentID]; exists {
		activity.EndTime = &now
		activity.Duration = int(now.Sub(activity.StartTime).Seconds())

		// 更新座席的时间统计
		s.updateAgentTimeStatistics(agent, activity.Status, activity.Duration)
	}

	// 创建新状态活动记录
	newActivity := &model.AgentActivity{
		ID:           fmt.Sprintf("activity_%d_%s", now.UnixNano(), agentID),
		AgentID:      agentID,
		ActivityType: "status_change",
		Status:       newStatus,
		StartTime:    now,
		Notes:        fmt.Sprintf("Status changed to %s", newStatus),
	}
	s.agentActivities[newActivity.ID] = newActivity
	s.currentActivities[agentID] = newActivity

	// 更新座席状态
	oldStatus := agent.Status
	agent.Status = newStatus
	agent.LastActivity = &now

	// 如果状态变为忙碌，则记录当前活动电话
	if newStatus == model.AgentStatusBusy && agent.CurrentCallID != "" {
		newActivity.CallID = agent.CurrentCallID
		newActivity.Notes = fmt.Sprintf("Status changed to busy for call %s", agent.CurrentCallID)
	}

	// 更新ACD队列中的座席状态
	if s.acdEngine != nil && agent.ACDEnabled {
		// 从所有队列中更新座席状态
		queues := s.acdEngine.ListQueues()
		for _, queue := range queues {
			_ = s.acdEngine.UpdateAgentStatus(agentID, queue.ID, newStatus)
		}
	}

	log.Printf("Agent %s (%s) status changed from %s to %s", agent.FullName, agentID, oldStatus, newStatus)
	return nil
}

// StartAfterCallWork 开始事后处理
func (s *AgentService) StartAfterCallWork(agentID string, callID string) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 验证座席存在
	agent, exists := s.agents[agentID]
	if !exists {
		return errors.New("agent not found")
	}

	// 检查座席状态
	if agent.Status != model.AgentStatusBusy {
		return errors.New("agent is not on a call")
	}

	// 检查是否是当前通话
	if agent.CurrentCallID != callID {
		return errors.New("call ID does not match current call")
	}

	// 结束当前活动
	now := time.Now()
	if activity, exists := s.currentActivities[agentID]; exists {
		activity.EndTime = &now
		activity.Duration = int(now.Sub(activity.StartTime).Seconds())

		// 更新座席的通话统计
		agent.TotalTalkTime += activity.Duration
		agent.TotalCalls++
		if agent.TotalCalls > 0 {
			agent.AverageTalkTime = agent.TotalTalkTime / agent.TotalCalls
		}

		// 更新座席的忙碌时间
		s.updateAgentTimeStatistics(agent, activity.Status, activity.Duration)
	}

	// 创建事后处理活动记录
	activity := &model.AgentActivity{
		ID:           fmt.Sprintf("activity_%d_%s", now.UnixNano(), agentID),
		AgentID:      agentID,
		ActivityType: "wrapup",
		Status:       model.AgentStatusWrapup,
		CallID:       callID,
		StartTime:    now,
		Notes:        "Started after call work",
	}
	s.agentActivities[activity.ID] = activity
	s.currentActivities[agentID] = activity

	// 更新座席状态
	agent.Status = model.AgentStatusWrapup
	agent.CurrentCallID = "" // 清除当前通话ID
	agent.LastActivity = &now

	// 更新ACD队列中的座席状态
	if s.acdEngine != nil && agent.ACDEnabled {
		queues := s.acdEngine.ListQueues()
		for _, queue := range queues {
			_ = s.acdEngine.UpdateAgentStatus(agentID, queue.ID, model.AgentStatusWrapup)
		}
	}

	// 启动自动完成事后处理的计时器
	go func() {
		// 获取默认事后处理时间
		wrapupTime := 60 // 默认60秒
		if settings, exists := s.agentSettings[agentID]; exists {
			wrapupTime = settings.DefaultWrapupTime
		}

		// 等待指定时间后自动转为可用状态
		time.Sleep(time.Duration(wrapupTime) * time.Second)
		_ = s.FinishAfterCallWork(agentID)
	}()

	log.Printf("Agent %s (%s) started after call work for call %s", agent.FullName, agentID, callID)
	return nil
}

// FinishAfterCallWork 结束事后处理
func (s *AgentService) FinishAfterCallWork(agentID string) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 验证座席存在
	agent, exists := s.agents[agentID]
	if !exists {
		return errors.New("agent not found")
	}

	// 检查座席状态
	if agent.Status != model.AgentStatusWrapup {
		return errors.New("agent is not in wrapup state")
	}

	// 结束当前活动
	now := time.Now()
	if activity, exists := s.currentActivities[agentID]; exists {
		activity.EndTime = &now
		activity.Duration = int(now.Sub(activity.StartTime).Seconds())

		// 更新座席的事后处理时间
		s.updateAgentTimeStatistics(agent, activity.Status, activity.Duration)
	}

	// 创建活动记录
	activity := &model.AgentActivity{
		ID:           fmt.Sprintf("activity_%d_%s", now.UnixNano(), agentID),
		AgentID:      agentID,
		ActivityType: "status_change",
		Status:       model.AgentStatusAvailable,
		StartTime:    now,
		Notes:        "Finished after call work",
	}
	s.agentActivities[activity.ID] = activity
	s.currentActivities[agentID] = activity

	// 更新座席状态
	agent.Status = model.AgentStatusAvailable
	agent.LastActivity = &now

	// 更新ACD队列中的座席状态
	if s.acdEngine != nil && agent.ACDEnabled {
		queues := s.acdEngine.ListQueues()
		for _, queue := range queues {
			_ = s.acdEngine.UpdateAgentStatus(agentID, queue.ID, model.AgentStatusAvailable)
		}
	}

	log.Printf("Agent %s (%s) finished after call work", agent.FullName, agentID)
	return nil
}

// 座席管理

// CreateAgent 创建座席
func (s *AgentService) CreateAgent(agent *model.Agent) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 检查是否已存在
	if _, exists := s.agents[agent.ID]; exists {
		return errors.New("agent already exists")
	}

	// 设置默认值
	if agent.Status == "" {
		agent.Status = model.AgentStatusOffline
	}
	if agent.Extension == "" {
		agent.Extension = agent.ID // 使用ID作为默认分机
	}

	// 创建默认设置
	defaultSettings := &model.AgentSettings{
		ID:                fmt.Sprintf("settings_%s", agent.ID),
		AgentID:           agent.ID,
		AutoAnswer:        false,
		PlayRingTone:      true,
		PopupCallInfo:     true,
		ShowWallboard:     true,
		DefaultWrapupTime: 60,
		Language:          "zh-CN",
		Theme:             "light",
		UpdatedAt:         time.Now(),
	}

	// 保存座席和设置
	s.agents[agent.ID] = agent
	s.agentSettings[agent.ID] = defaultSettings

	log.Printf("Created new agent: %s (%s)", agent.FullName, agent.ID)
	return nil
}

// UpdateAgent 更新座席信息
func (s *AgentService) UpdateAgent(agent *model.Agent) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 验证座席存在
	existingAgent, exists := s.agents[agent.ID]
	if !exists {
		return errors.New("agent not found")
	}

	// 保留一些不变的字段
	agent.Status = existingAgent.Status
	agent.LoginTime = existingAgent.LoginTime
	agent.LogoutTime = existingAgent.LogoutTime
	agent.LastActivity = existingAgent.LastActivity
	agent.CurrentCallID = existingAgent.CurrentCallID
	agent.AvailableTime = existingAgent.AvailableTime
	agent.BusyTime = existingAgent.BusyTime
	agent.BreakTime = existingAgent.BreakTime
	agent.WrapupTime = existingAgent.WrapupTime
	agent.TotalCalls = existingAgent.TotalCalls
	agent.TotalTalkTime = existingAgent.TotalTalkTime
	agent.AverageTalkTime = existingAgent.AverageTalkTime

	// 更新座席信息
	s.agents[agent.ID] = agent

	log.Printf("Updated agent information: %s (%s)", agent.FullName, agent.ID)
	return nil
}

// GetAgent 获取座席信息
func (s *AgentService) GetAgent(agentID string) (*model.Agent, error) {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	agent, exists := s.agents[agentID]
	if !exists {
		return nil, errors.New("agent not found")
	}

	return agent, nil
}

// ListAgents 列出所有座席
func (s *AgentService) ListAgents() []*model.Agent {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	agents := make([]*model.Agent, 0, len(s.agents))
	for _, agent := range s.agents {
		agents = append(agents, agent)
	}

	return agents
}

// DeleteAgent 删除座席
func (s *AgentService) DeleteAgent(agentID string) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 验证座席存在
	if _, exists := s.agents[agentID]; !exists {
		return errors.New("agent not found")
	}

	// 检查座席是否在线
	agent := s.agents[agentID]
	if agent.Status != model.AgentStatusOffline {
		return errors.New("cannot delete an online agent")
	}

	// 从所有队列中移除座席
	if s.acdEngine != nil {
		queues := s.acdEngine.ListQueues()
		for _, queue := range queues {
			_ = s.acdEngine.RemoveAgentFromQueue(agentID, queue.ID)
		}
	}

	// 删除座席相关信息
	delete(s.agents, agentID)
	delete(s.agentSettings, agentID)

	// 删除活动记录（可选）
	// 这里可以保留活动记录用于历史分析

	log.Printf("Deleted agent: %s (%s)", agent.FullName, agentID)
	return nil
}

// 更新座席设置

// UpdateAgentSettings 更新座席设置
func (s *AgentService) UpdateAgentSettings(agentID string, settings *model.AgentSettings) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 验证座席存在
	if _, exists := s.agents[agentID]; !exists {
		return errors.New("agent not found")
	}

	// 确保设置ID正确
	settings.ID = fmt.Sprintf("settings_%s", agentID)
	settings.AgentID = agentID
	settings.UpdatedAt = time.Now()

	// 保存设置
	s.agentSettings[agentID] = settings

	log.Printf("Updated settings for agent: %s", agentID)
	return nil
}

// GetAgentSettings 获取座席设置
func (s *AgentService) GetAgentSettings(agentID string) (*model.AgentSettings, error) {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	// 验证座席存在
	if _, exists := s.agents[agentID]; !exists {
		return nil, errors.New("agent not found")
	}

	// 获取设置，如果不存在则返回默认设置
	settings, exists := s.agentSettings[agentID]
	if !exists {
		// 创建并返回默认设置
		defaultSettings := &model.AgentSettings{
			ID:                fmt.Sprintf("settings_%s", agentID),
			AgentID:           agentID,
			AutoAnswer:        false,
			PlayRingTone:      true,
			PopupCallInfo:     true,
			ShowWallboard:     true,
			DefaultWrapupTime: 60,
			Language:          "zh-CN",
			Theme:             "light",
			UpdatedAt:         time.Now(),
		}
		return defaultSettings, nil
	}

	return settings, nil
}

// 座席统计和活动

// GetAgentStatistics 获取座席统计信息
func (s *AgentService) GetAgentStatistics(agentID string) (*model.AgentStatistics, error) {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	// 验证座席存在
	agent, exists := s.agents[agentID]
	if !exists {
		return nil, errors.New("agent not found")
	}

	// 创建统计信息
	stats := &model.AgentStatistics{
		ID:                    fmt.Sprintf("stats_%s_%s", agentID, time.Now().Format("20060102")),
		AgentID:               agentID,
		Date:                  time.Now(),
		AvailableTime:         agent.AvailableTime,
		BusyTime:              agent.BusyTime,
		BreakTime:             agent.BreakTime,
		WrapupTime:            agent.WrapupTime,
		TotalCalls:            agent.TotalCalls,
		TotalTalkTime:         agent.TotalTalkTime,
		AverageTalkTime:       agent.AverageTalkTime,
		TotalAfterCallWorkTime: agent.WrapupTime,
		CreatedAt:             time.Now(),
	}

	return stats, nil
}

// GetAgentActivities 获取座席活动记录
func (s *AgentService) GetAgentActivities(agentID string, startTime, endTime time.Time) []*model.AgentActivity {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	var activities []*model.AgentActivity
	for _, activity := range s.agentActivities {
		if activity.AgentID == agentID && 
		   activity.StartTime.After(startTime) && 
		   activity.StartTime.Before(endTime) {
			activities = append(activities, activity)
		}
	}

	return activities
}

// 辅助方法

// isValidStatusChange 验证状态变更是否有效
func (s *AgentService) isValidStatusChange(currentStatus, newStatus model.AgentStatus) bool {
	// 定义有效的状态转换
	validTransitions := map[model.AgentStatus][]model.AgentStatus{
		model.AgentStatusOffline: {
			model.AgentStatusLoggedIn,
		},
		model.AgentStatusLoggedIn: {
			model.AgentStatusAvailable,
			model.AgentStatusOnBreak,
			model.AgentStatusOffline,
		},
		model.AgentStatusAvailable: {
			model.AgentStatusBusy,      // 接到电话
			model.AgentStatusOnBreak,
			model.AgentStatusOffline,
		},
		model.AgentStatusBusy: {
			model.AgentStatusAvailable, // 直接回到可用
			model.AgentStatusWrapup,    // 进入事后处理
			model.AgentStatusOffline,
		},
		model.AgentStatusWrapup: {
			model.AgentStatusAvailable, // 完成事后处理
			model.AgentStatusOnBreak,
			model.AgentStatusOffline,
		},
		model.AgentStatusOnBreak: {
			model.AgentStatusAvailable,
			model.AgentStatusOffline,
		},
	}

	// 检查是否允许转换
	allowedStatuses, exists := validTransitions[currentStatus]
	if !exists {
		return false
	}

	for _, status := range allowedStatuses {
		if status == newStatus {
			return true
		}
	}

	return false
}

// updateAgentTimeStatistics 更新座席时间统计
func (s *AgentService) updateAgentTimeStatistics(agent *model.Agent, status model.AgentStatus, duration int) {
	switch status {
	case model.AgentStatusAvailable:
		agent.AvailableTime += duration
	case model.AgentStatusBusy:
		agent.BusyTime += duration
	case model.AgentStatusOnBreak:
		agent.BreakTime += duration
	case model.AgentStatusWrapup:
		agent.WrapupTime += duration
	}
}